#include <jni.h>
#include <string>
#include <dirent.h>
#include "LogUtils.h"
#include "TimeUtils.h"
#include <android/bitmap.h>





extern "C" JNIEXPORT jstring JNICALL
Java_com_xixilala_ndkdemo_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

extern "C" JNIEXPORT jint JNICALL
Java_com_xixilala_ndkdemo_MainActivity_calPlus(JNIEnv *env, jobject thiz, jint p1, jint p2) {



    return p1 + p2;
}


namespace p1 {
    int age = 12;
    int height = 170;
}
namespace p2 {
    int age = 22;
    int height = 200;
}


extern "C" {
    using namespace p2; //切换p1/p2可以使用不同的age
    JNIEXPORT void JNICALL
    Java_com_xixilala_ndkdemo_MainActivity_printLog(JNIEnv *env, jobject thiz) {
        LOGD("LOG Hello from C++")

        LOGD("----age=%d",age)
    }
}

extern "C"
JNIEXPORT jintArray JNICALL
Java_com_xixilala_ndkdemo_MainActivity_funUseTime(JNIEnv *env, jobject thiz, jintArray image_bytes, jint bm_width, jint bm_height) {


    jint *data;
    data = env->GetIntArrayElements(image_bytes, NULL);
    if (data == NULL) {
        return 0;
    }
    int alpha = 0xFF << 24;

    __TIC1__(alpha)

    // 灰度处理
    for (int i=0; i< bm_height ; i++) {
        for (int j=0; j< bm_width ; j++) {
            int color = data[bm_width*i+j];
            int red = (color&0x00FF0000)>>16;
            int green = (color&0x0000FF00)>>8;
            int blue = (color&0x000000FF);
            color = (red + green + blue) /3;
            color = alpha | (color << 16) | (color << 8) | color;
            data[bm_width*i+j] = color;
        }
    }
    int size = bm_width*bm_height;
    jintArray result = env->NewIntArray(size);
    env->SetIntArrayRegion(result,0,size, data);
    env->ReleaseIntArrayElements(image_bytes,data,0);

    __TOC1__(alpha)

    return result ;
}


extern "C" { // 这个是以下代码按照C语言编译，而不是c++
    using namespace std; // 使用标准的命名空间

    void showAllFiles(string dir_name) {

        if (dir_name.empty()) {
            LOGD("dir_name is empty")
            return;
        }
        DIR *dir = opendir(dir_name.c_str());
        if (dir == NULL) {
            LOGD("Can not open dir. Check path or permission")
            return;
        }
        struct dirent *file;
        while((file=readdir(dir)) != NULL) {
            if ((strcmp(file->d_name,".") == 0 || strcmp(file->d_name,"..") == 0)){
                LOGD("IGNORE . AND ..")
                continue;
            }

            if (file->d_type == DT_DIR) {
                string filePath = dir_name + "/" + file->d_name;
                showAllFiles(filePath);
            } else {
                LOGI("filePath: %s/%s", dir_name.c_str(), file->d_name)
            }
        }
        closedir(dir);
    }

    JNIEXPORT void JNICALL
    Java_com_xixilala_ndkdemo_MainActivity_showThePathFiles(JNIEnv *env, jobject thiz,
                                                            jstring file_path) {

        const char *dirPath = env->GetStringUTFChars(file_path,0);
        showAllFiles(dirPath);
        env->ReleaseStringUTFChars(file_path, dirPath);

    }
}


extern "C"
JNIEXPORT void JNICALL
Java_com_xixilala_ndkdemo_MainActivity_getBitmapInfoC(JNIEnv *env, jobject thiz, jobject bm) {

    if (bm == NULL) {
        LOGD("android bitmap IS NULL")
        return;
    }

    AndroidBitmapInfo info;
    int result;

    result = AndroidBitmap_getInfo(env, bm, &info);
    if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
        LOGD("android bitmap get info failed result:%d",result)
        return;
    }

    LOGD("android bitmap info : width=%d height=%d format=%d stride=%d ", info.width,info.height,info.format,info.stride)

    unsigned char *addrPtr;
    result = AndroidBitmap_lockPixels(env,bm, reinterpret_cast<void **>(&addrPtr));

    if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
        LOGD("android bitmap lock pixels failed result:%d",result)
        return;
    }

    int length = info.stride * info.height;
    for (int i = 0; i < length; ++i) {
        LOGD("android bitmap value = %x", addrPtr[i])
    }

    result = AndroidBitmap_unlockPixels(env, bm);
    if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
        LOGD("android bitmap unlock pixels failed result:%d",result)
        return;
    }
}


extern "C"
JNIEXPORT void JNICALL
Java_com_xixilala_ndkdemo_MainActivity_someCommonApiCall(JNIEnv *env, jobject thiz) {
    // https://blog.csdn.net/afei__/article/details/81016413
    int v = env->GetVersion();
    LOGD("env version = %d" , v)

    jclass stringClass = env->FindClass("java/lang/String");
    LOGD("env findClass %x" ,stringClass)

    jclass  stringSuperClass = env->GetSuperclass(stringClass);
    LOGD("env GetSuperclass %x" , stringSuperClass)

    jboolean  isAssignable = env->IsAssignableFrom(stringClass, stringSuperClass);
    LOGD("env IsAssignableFrom stringClass to stringSuperClass %s" , isAssignable?"true":"false")

    jstring stringObject = static_cast<jstring>(env->AllocObject(stringClass));
    LOGD("env stringObject %x" , stringObject)

    jmethodID stringConstructorMethodId = env->GetMethodID(stringClass,"<init>","()V");
    jstring stringObjectByMethodId = static_cast<jstring>(env->NewObject(stringClass, stringConstructorMethodId));
    LOGD("env stringObjectByMethodId %x" , stringObjectByMethodId);

/***
二、获取版本

1. jint GetVersion()

三、类操作

1. jclass FindClass(const char* name)

2. jclass GetSuperclass(jclass clazz)

3. jboolean IsAssignableFrom(jclass clazz1, jclass clazz2)

四、对象操作

1. jobject AllocObject(jclass clazz)

2. jobject NewObject(jclass clazz, jmethodID methodID, …)

3. jobject NewObjectA(jclass clazz, jmethodID methodID, jvalue* args)

4. jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args)

5. jclass GetObjectClass(jobject obj)

6. jobjectRefType GetObjectRefType(jobject obj)

7. jboolean IsInstanceOf(jobject obj, jclass clazz)

8. jboolean IsSameObject(jobject ref1, jobject ref2)

五、域操作

1. jfieldID GetFieldID(jclass clazz, const char name, const char sig)

2. NativeType GetField(jobject obj, jfieldID fieldID)

3. void SetField(jobject obj, jfieldID fieldID, NativeType value)

4. jfieldID GetStaticFieldID(jclass clazz, const char name, const char sig)

5. NativeType GetStaticField(jobject obj, jfieldID fieldID);

6. void SetStaticField(jobject obj, jfieldID fieldID, NativeType value)

六、方法操作

1. jmethodID GetMethodID(jclass clazz, const char name, const char sig)

2. NativeType CallMethod(jobject obj, jmethodID methodID, …)

3. NativeType CallMethodA(jobject obj, jmethodID methodID, jvalue* args)

4. NativeType CallMethodV(jobject obj, jmethodID methodID, va_list args)

5. jmethodID GetStaticMethodID(jclass clazz, const char name, const char sig)

6. NativeType CallStaticMethod(jclass clazz, jmethodID methodID, …)

7. NativeType CallStaticMethodA(jclass clazz, jmethodID methodID, jvalue* args)

8. NativeType CallStaticMethodV(jclass clazz, jmethodID methodID, va_list args)

七、全局引用和局部引用

1. jobject NewGlobalRef(jobject obj)

2. void DeleteGlobalRef(jobject globalRef)

3. jobject NewLocalRef(jobject ref)

4. void DeleteLocalRef(jobject localRef)

5. jweak NewWeakGlobalRef(jobject obj)

6. void DeleteWeakGlobalRef(jweak obj)

八、字符串操作

1. jstring NewString(const jchar* unicodeChars, jsize len)

2. jstring NewStringUTF(const char* bytes)

3. jsize GetStringLength(jstring string)

4. jsize GetStringUTFLength(jstring string)

5. const jchar GetStringChars(jstring string, jboolean isCopy)

6. const char GetStringUTFChars(jstring string, jboolean isCopy)

7. void ReleaseStringChars(jstring string, const jchar* chars)

8. void ReleaseStringUTFChars(jstring string, const char* utf)

九、数组操作

1. jobjectArray NewObjectArray(jsize length, jclass elementClass, jobject initialElement)

2.ArrayType NewArray(jsize length)

3. jsize GetArrayLength(jarray array)

4. jobject GetObjectArrayElement(jobjectArray array, jsize index)

5. void SetObjectArrayElement(jobjectArray array, jsize index, jobject value)

6. NativeType GetArrayElements(ArrayType array, jboolean isCopy)

7. void ReleaseArrayElements(ArrayType array, NativeType* elems, jint mode)

8. void GetArrayRegion(ArrayType array, jsize start, jsize len, NativeType* buf)

9. void SetArrayRegion(ArrayType array, jsize start, jsize len, const NativeType* buf)

十、异常操作

1. jint Throw(jthrowable obj)

2. jint ThrowNew(jclass clazz, const char* message)

3. jthrowable ExceptionOccurred()

4. jboolean ExceptionCheck()

5. void ExceptionDescribe()

6. void ExceptionClear()

7. void FatalError(const char* msg)

*/



}



